home *** CD-ROM | disk | FTP | other *** search
- Subject: v24i087: A program to trace through symlinks
- Newsgroups: comp.sources.unix
- Approved: rsalz@uunet.UU.NET
- X-Checksum-Snefru: 6665b1eb fb4b370c d97bf4ca 713902c0
-
- Submitted-by: Roger Southwick <rogers@fangorn.wr.tek.com>
- Posting-number: Volume 24, Issue 87
- Archive-name: namei
-
- [ I wrote the Makefile. --r$ ]
-
- This program takes a set of pathnames. It scans each component in turn and
- follows symlinks until it reaches the end of the pathname. It prints
- the results of interpreting each directory component. Requires the lstat
- system call and the S_IFLINK inode type.
-
- -Roger (rogers@fangorn.wr.tek.com)
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 1 (of 1)."
- # Contents: README namei.1 namei.c
- # Wrapped by rogers@fangorn on Wed Mar 20 17:51:06 1991
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f README -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"README\"
- else
- echo shar: Extracting \"README\" \(989 characters\)
- sed "s/^X//" >README <<'END_OF_README'
- XTired of running into "Too many levels of symlinks" problems on
- Xyour 4.2 BSD derivitive machine?
- X
- XWe sure did... our NFS'ed network of lots of Suns, Vaxen and so forth
- Xmade it impossible at times to trace down where a file REALLY lived.
- XI mean ls -l is nice, but wouldn't you like to follow things like
- Xthe namei routine in the kernel does?
- X
- XWell here it is.... the namei program. It follows things out until
- Xa terminal state is found.
- X
- XThis program compiles and runs under:
- X
- X SunOS 4.0.1 (sun3's)
- X SunOS 4.0.3 (sun4's)
- X SunOS 4.1.1 (sun4's)
- X Ultrix 3.1
- X BSD 4.3
- X
- Xand probably a host of other 4.2 derived systems (but probably not
- XSystem V).
- X
- XAnyway, if anyone has any bugs (or enhancements), please send them to
- Xme in E-mail form.
- X
- XAnd, by the way, if you make LOTS of money off of this program, please
- Xdon't tell me :-).
- X
- X -Roger (rogers@fangorn.wr.tek.com)
- X UUCP: ...!uunet!tektronix!fangorn.wr.tek.com!rogers
- X ARPA: <rogers%fangorn.wr.tek.com@RELAY.CS.NET>
- END_OF_README
- if test 989 -ne `wc -c <README`; then
- echo shar: \"README\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f namei.1 -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"namei.1\"
- else
- echo shar: Extracting \"namei.1\" \(1496 characters\)
- sed "s/^X//" >namei.1 <<'END_OF_namei.1'
- X.\"
- X.\" Version 1.4 of namei
- X.\"
- X.TH NAMEI 1 "Local"
- X.SH NAME
- Xnamei - follow a pathname until a terminal point is found
- X.SH SYNOPSIS
- X.B namei
- X.I [-mx]
- X.I pathname
- X.I "[ pathname ... ]"
- X.SH DESCRIPTION
- X.I Namei
- Xuses its arguments as pathnames to any type
- Xof Unix file (symlinks, files, directories, and so forth).
- X.I Namei
- Xthen follows each pathname until a terminal
- Xpoint is found (a file, directory, char device, etc).
- XIf it finds a symbolic link, we show the link, and start
- Xfollowing it, indenting the output to show the context.
- X.PP
- XThis program is useful for finding a "too many levels of
- Xsymbolic links" problems.
- X.PP
- XFor each line output,
- X.I namei
- Xoutputs a the following characters to identify the file types found:
- X.LP
- X.nf
- X f: = the pathname we are currently trying to resolve
- X d = directory
- X l = symbolic link (both the link and it's contents are output)
- X s = socket
- X b = block device
- X c = character device
- X - = regular file
- X ? = an error of some kind
- X.fi
- X.PP
- X.I Namei
- Xprints an informative message when
- Xthe maximum number of symbolic links this system can have has been exceeded.
- X.SH OPTIONS
- X.TP 8
- X.B -x
- XShow mount point directories with a 'D', rather than a 'd'.
- X.TP 8
- X.B -m
- XShow the mode bits of each file type in octal notation.
- X.SH AUTHOR
- XRoger Southwick (rogers@amadeus.wr.tek.com)
- X.SH BUGS
- XTo be discovered.
- X.SH CAVEATS
- X.I Namei
- Xwill follow an infinite loop of symbolic links forever. To escape, use
- XSIGINT (usually ^C).
- X.SH "SEE ALSO"
- Xls(1), stat(1)
- END_OF_namei.1
- if test 1496 -ne `wc -c <namei.1`; then
- echo shar: \"namei.1\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f namei.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"namei.c\"
- else
- echo shar: Extracting \"namei.c\" \(5724 characters\)
- sed "s/^X//" >namei.c <<'END_OF_namei.c'
- X/*-------------------------------------------------------------
- X
- XThe namei program
- X
- XBy: Roger S. Southwick
- X
- XMay 2, 1990
- X
- Xusage: namei pathname [pathname ... ]
- X
- XThis program reads it's arguments as pathnames to any type
- Xof Unix file (symlinks, files, directories, and so forth).
- XThe program then follows each pathname until a terminal
- Xpoint is found (a file, directory, char device, etc).
- XIf it finds a symbolic link, we show the link, and start
- Xfollowing it, indenting the output to show the context.
- X
- XThis program is useful for finding a "too many levels of
- Xsymbolic links" problems.
- X
- XFor each line output, the program puts a file type first:
- X
- X f: = the pathname we are currently trying to resolve
- X d = directory
- X D = directory that is a mount point
- X l = symbolic link (both the link and it's contents are output)
- X s = socket
- X b = block device
- X c = character device
- X - = regular file
- X ? = an error of some kind
- X
- XThe program prints an informative messages when we exceed
- Xthe maximum number of symbolic links this system can have.
- X
- XThe program exits with a 1 status ONLY if it finds it cannot
- Xchdir to /, or if it encounters an unknown file type.
- X
- X-------------------------------------------------------------*/
- X
- X#ifndef lint
- Xstatic char *RCSid = "$Id: namei.c,v 1.4 91/03/20 17:44:11 rogers Release_1 $";
- X#endif
- X
- X#include <stdio.h>
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#include <sys/param.h>
- X
- Xextern char *sys_errlist[];
- Xextern int errno;
- X#define ERR sys_errlist[errno],errno
- X
- Xint symcount;
- Xint mflag = 0;
- Xint xflag = 0;
- X
- Xmain(argc, argv)
- Xint argc;
- Xchar *argv[];
- X{
- X void namei(), usage();
- X char *getwd();
- X int getopt();
- X extern int optind;
- X register int c;
- X char curdir[MAXPATHLEN];
- X
- X if(argc < 2)
- X usage();
- X
- X while((c = getopt(argc, argv, "mx")) != EOF){
- X switch(c){
- X case 'm':
- X mflag++;
- X break;
- X
- X case 'x':
- X xflag++;
- X break;
- X
- X case '?':
- X default:
- X usage();
- X }
- X }
- X
- X if(getwd(curdir) == NULL){
- X (void)fprintf(stderr, "namei: unable to get current directory - %s\n", curdir);
- X exit(1);
- X }
- X
- X
- X for(; optind < argc; optind++){
- X (void)printf("f: %s\n", argv[optind]);
- X symcount = 1;
- X namei(argv[optind], 0);
- X
- X if(chdir(curdir) == -1){
- X (void)fprintf(stderr, "namei: unable to chdir to %s - %s (%d)\n", curdir, ERR);
- X exit(1);
- X }
- X }
- X exit(0);
- X}
- X
- Xvoid
- Xusage()
- X{
- X (void)fprintf(stderr,"usage: namei [-mx] pathname [pathname ...]\n");
- X exit(1);
- X}
- X
- X#ifndef NODEV
- X#define NODEV (dev_t)(-1)
- X#endif
- X
- Xvoid
- Xnamei(file, lev)
- X
- Xregister char *file;
- Xregister int lev;
- X{
- X register char *cp;
- X char buf[BUFSIZ], sym[BUFSIZ];
- X struct stat stb;
- X register int i;
- X dev_t lastdev = NODEV;
- X
- X /*
- X * See if the file has a leading /, and if so cd to root
- X */
- X
- X if(*file == '/'){
- X while(*file == '/')
- X file++;
- X
- X if(chdir("/") == -1){
- X (void)fprintf(stderr,"namei: could not chdir to root!\n");
- X exit(1);
- X }
- X for(i = 0; i < lev; i++)
- X (void)printf(" ");
- X
- X if(stat("/", &stb) == -1){
- X (void)fprintf(stderr, "namei: could not stat root!\n");
- X exit(1);
- X }
- X lastdev = stb.st_dev;
- X
- X if(mflag)
- X (void)printf(" d %04o /\n", stb.st_mode & 07777);
- X else
- X (void)printf(" d /\n");
- X }
- X
- X for(;;){
- X
- X /*
- X * Copy up to the next / (or nil) into buf
- X */
- X
- X for(cp = buf; *file != '\0' && *file != '/'; cp++, file++)
- X *cp = *file;
- X
- X while(*file == '/') /* eat extra /'s */
- X file++;
- X
- X *cp = '\0';
- X
- X if(buf[0] == '\0'){
- X
- X /*
- X * Buf is empty, so therefore we are done
- X * with this level of file
- X */
- X
- X return;
- X }
- X
- X for(i = 0; i < lev; i++)
- X (void)printf(" ");
- X
- X /*
- X * See what type of critter this file is
- X */
- X
- X if(lstat(buf, &stb) == -1){
- X (void)printf(" ? %s - %s (%d)\n", buf, ERR);
- X return;
- X }
- X
- X switch(stb.st_mode & S_IFMT){
- X case S_IFDIR:
- X
- X /*
- X * File is a directory, chdir to it
- X */
- X
- X if(chdir(buf) == -1){
- X (void)printf(" ? could not chdir into %s - %s (%d)\n", buf, ERR );
- X return;
- X }
- X if(xflag && lastdev != stb.st_dev && lastdev != NODEV){
- X /* Across mnt point */
- X if(mflag)
- X (void)printf(" D %04o %s\n", stb.st_mode & 07777, buf);
- X else
- X (void)printf(" D %s\n", buf);
- X }
- X else {
- X if(mflag)
- X (void)printf(" d %04o %s\n", stb.st_mode & 07777, buf);
- X else
- X (void)printf(" d %s\n", buf);
- X }
- X lastdev = stb.st_dev;
- X
- X (void)fflush(stdout);
- X break;
- X
- X case S_IFLNK:
- X /*
- X * Sigh, another symlink. Read it's contents and
- X * call namei()
- X */
- X
- X bzero(sym, BUFSIZ);
- X if(readlink(buf, sym, BUFSIZ) == -1){
- X (void)printf(" ? problems reading symlink %s - %s (%d)\n", buf, ERR);
- X return;
- X }
- X
- X if(mflag)
- X (void)printf(" l %04o %s -> %s", stb.st_mode & 07777, buf, sym);
- X else
- X (void)printf(" l %s -> %s", buf, sym);
- X
- X if(symcount > 0 && symcount++ > MAXSYMLINKS){
- X (void)printf(" *** EXCEEDED UNIX LIMIT OF SYMLINKS ***");
- X symcount = -1;
- X }
- X (void)printf("\n");
- X namei(sym, lev + 1);
- X break;
- X
- X case S_IFCHR:
- X if(mflag)
- X (void)printf(" c %04o %s\n", stb.st_mode & 07777, buf);
- X else
- X (void)printf(" c %s\n", buf);
- X break;
- X
- X case S_IFBLK:
- X if(mflag)
- X (void)printf(" b %04o %s\n", stb.st_mode & 07777, buf);
- X else
- X (void)printf(" b %s\n", buf);
- X break;
- X
- X case S_IFSOCK:
- X if(mflag)
- X (void)printf(" s %04o %s\n", stb.st_mode & 07777, buf);
- X else
- X (void)printf(" s %s\n", buf);
- X break;
- X
- X case S_IFREG:
- X if(mflag)
- X (void)printf(" - %04o %s\n", stb.st_mode & 07777, buf);
- X else
- X (void)printf(" - %s\n", buf);
- X break;
- X
- X default:
- X (void)fprintf(stderr,"namei: unknown file type 0%06o on file %s\n", stb.st_mode, buf );
- X exit(1);
- X
- X }
- X }
- X}
- X
- END_OF_namei.c
- if test 5724 -ne `wc -c <namei.c`; then
- echo shar: \"namei.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- echo shar: End of archive 1 \(of 1\).
- cp /dev/null ark1isdone
- MISSING=""
- for I in 1 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 1 archives.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
- --
- -Roger (rogers@fangorn.wr.tek.com)
- UUCP: ...!uunet!tektronix!fangorn.wr.tek.com!rogers
- ARPA: <rogers%fangorn.wr.tek.com@RELAY.CS.NET>
-
- exit 0 # Just in case...
-